# import bpy
from typing import Callable, List
# from ...addon.naming import FluidLabNaming
from ...libs.functions.animation import anim_attrs
from bpy.types import Context, Operator, ParticleSettings
from ...libs.functions.animation import remove_keyframe_x
from ...libs.functions.get_common_vars import get_common_vars
from ...properties.lists.props_list_fluid_groups import FluidGroupsListItem
from ...properties.lists.active_emitter_props import ActiveEmitterPhysicsProps, ActiveEmitterEmissionProps


def apply_common_code(context:Context, callback:Callable, call_from:str) -> None:

    """ Soft Start y Soft End  APPLY """

    fluid_groups = get_common_vars(context, get_fluid_groups=True)
    active_group = fluid_groups.active

    emitters_list = active_group.emitters
    emitters = emitters_list.get_all_emitters
    
    active_emitter_item = emitters_list.active
    emission_props = active_emitter_item.emission
    physics_props  = active_emitter_item.physics

    # Solo tocamos el fluid radius (el interaction radius) si es el soft start:
    if call_from == "start":

        # Guardo el estado previo de fluid_radius (para poder restaurarlo luego):
        physics_props.prev_fluid_radius = physics_props.fluid_radius

        # Lo seteo para que se seteen a los emisores:
        physics_props.fluid_radius = emission_props.fluid_radius 

        # Lo marco como animado:
        emission_props.fluid_radius_animed = True

    for emitter_ob in emitters:

        psys_active = emitter_ob.particle_systems.active
        if not psys_active:
            continue

        p_settigns = psys_active.settings
        
        dpaths = ("drag_factor", "damping")
        for dpath in dpaths:

            callback(active_group, p_settigns, dpath, emission_props, physics_props)


def remove_common_code(self, context:Context, active_group:FluidGroupsListItem, fs:str, keyframes:List[int], physics_props:ActiveEmitterPhysicsProps) -> None:

    """ Soft Start y Soft End  REMOVE """
    
    scn = get_common_vars(context, get_scn=True)
    emitters_list = active_group.emitters

    # Sugiero el current frame:
    setattr(self, fs, scn.frame_current)

    # Elimino los keyframes:
    dpaths = ("drag_factor", "damping")
    all_p_settings = emitters_list.get_all_p_settings

    for dpath in dpaths:
        for kf in keyframes:
            remove_keyframe_x(dpath, all_p_settings, kf)
            value = getattr(physics_props, dpath)

    # Dejo los valores como tengamos en physics:
    for p_settings in all_p_settings:
        for dpath in dpaths:
            setattr(p_settings, dpath, value)


class FLUIDLAB_OT_fs_emission_soft_start_apply(Operator):
    bl_idname = "fluidlab.fs_emission_soft_start_apply"
    bl_label = "Soft Start"
    bl_description = "Add keyframes for Soft Start"
    bl_options = {"REGISTER", "UNDO"}

    
    def execute(self, context):

        """ Soft Start Apply """
        
        def callback(active_group:FluidGroupsListItem, p_settigns:ParticleSettings, dpath:str, emission_props:ActiveEmitterEmissionProps, physics_props:ActiveEmitterPhysicsProps) -> None:

            data =  {
                        'object':   p_settigns, 
                        'dpath':    dpath, 
                        'frame':    emission_props.ss_frame_start-1,
                        'value':    1
            }
            anim_attrs(data=data)
            
            # Guardo los keyframes:
            active_group.soft_start_add_frame(emission_props.ss_frame_start-1)

            data =  {
                        'object':   p_settigns, 
                        'dpath':    dpath, 
                        'frame':    emission_props.ss_frame_start,
                        'value':    getattr(physics_props, dpath)
            }
            anim_attrs(data=data)

            # Guardo los keyframes:
            active_group.soft_start_add_frame(emission_props.ss_frame_start)


        apply_common_code(context, callback, "start")

        return {'FINISHED'}


class FLUIDLAB_OT_fs_emission_soft_start_remove(Operator):
    bl_idname = "fluidlab.fs_emission_soft_start_remove"
    bl_label = "Soft Start"
    bl_description = "Remove keyframes for Soft Start"
    bl_options = {"REGISTER", "UNDO"}

    
    def execute(self, context):

        """ Soft Start Remove """
                    
        fluid_groups = get_common_vars(context, get_fluid_groups=True)
        active_group = fluid_groups.active
        keyframes = active_group.get_soft_start_keyframes

        emitters_list = active_group.emitters
        active_emitter_item = emitters_list.active
        emission_props = active_emitter_item.emission
        physics_props  = active_emitter_item.physics
       
        # Eliminamos los keyframes:
        remove_common_code(self, context, active_group, "ss_frame_start", keyframes, physics_props)        
        
        # Eliminamos los stored keyframes:
        active_group.clear_soft_start_keyframes
        
        # Restauro el valor previo que tuviera:
        print("Previous fluid radius", physics_props.prev_fluid_radius)
        physics_props.fluid_radius = physics_props.prev_fluid_radius
 
        # Lo desmarco como animado:
        emission_props.fluid_radius_animed = False

        # Salimos de modo soft start config:
        emission_props.soft_start = False
        
        return {'FINISHED'}


class FLUIDLAB_OT_fs_emission_soft_end_apply(Operator):
    bl_idname = "fluidlab.fs_emission_soft_end_apply"
    bl_label = "Soft End"
    bl_description = "Add keyframes for Soft End"
    bl_options = {"REGISTER", "UNDO"}

    
    def execute(self, context):

        """ Soft End Apply """

        def callback(active_group:FluidGroupsListItem, p_settigns:ParticleSettings, dpath:str, emission_props:ActiveEmitterEmissionProps, physics_props:ActiveEmitterPhysicsProps) -> None:

            data =  {
                        'object':   p_settigns, 
                        'dpath':    dpath, 
                        'frame':    emission_props.se_frame_start,
                        'value':    getattr(physics_props, dpath)
            }
            anim_attrs(data=data)
            
            # Guardo los keyframes:
            active_group.soft_end_add_frame(emission_props.se_frame_start)

            data =  {
                        'object':   p_settigns, 
                        'dpath':    dpath, 
                        'frame':    emission_props.se_frame_start+emission_props.se_duration,
                        'value':    emission_props.se_amount
            }
            anim_attrs(data=data)

            # Guardo los keyframes:
            active_group.soft_end_add_frame(emission_props.se_frame_start+emission_props.se_duration)
        
        apply_common_code(context, callback, "end")

        return {'FINISHED'}


class FLUIDLAB_OT_fs_emission_soft_end_remove(Operator):
    bl_idname = "fluidlab.fs_emission_soft_end_remove"
    bl_label = "Soft End"
    bl_description = "Remove keyframes for Soft End"
    bl_options = {"REGISTER", "UNDO"}

    
    def execute(self, context):

        """ Soft End Remove """

        fluid_groups = get_common_vars(context, get_fluid_groups=True)
        active_group = fluid_groups.active
        keyframes = active_group.get_soft_end_keyframes

        emitters_list = active_group.emitters
        active_emitter_item = emitters_list.active
        physics_props  = active_emitter_item.physics
        
        # Eliminamos los keyframes:
        remove_common_code(self, context, active_group, "se_frame_start", keyframes, physics_props)        
        
        # Eliminamos los stored keyframes:
        active_group.clear_soft_end_keyframes

        return {'FINISHED'}